<?php

namespace App\Services\MiniprogramToGame;

use App\Models\Log\LogWxMiniprogramJumpgame;
use App\Models\WxMiniprogramJumpgameConfig;
use App\Services\IpToolService;
use App\Services\ServiceBase;
use App\Services\WanSdk\WanSdkService;
use YQ\YqExtend;

class MiniprogramToGameService extends ServiceBase
{
    public function canJump($config, $openid, $params, $ipinfo = [], $scene = 0)
    {
        $now = time();

        // 判断状态
        if ($config->status != WxMiniprogramJumpgameConfig::STATUS_OPEN) {
            return false;
        }

        // 判断时间
        if ($config->start_time > $now || $now > $config->end_time) {
            return false;
        }

        // 是否配置了测试账号
        $test_openids = $config->test_openids;
        if (!empty($test_openids) && strpos($test_openids, $openid) === false) {
            return false;
        }

        // 概率
        $per = rand(1, 10000);
        if ($config->per < $per) {
            return false;
        }

        // 判断设备类型
        $device_list = json_decode($config->device_list, true);
        $device_type = WanSdkService::getInstance()->getPhoneType();
        if (!empty($device_list) && !in_array($device_type, $device_list)) {
            return false;
        }

        // 判断小程序路径参数
        if (!empty($config->query)) {
            $query = $config->query;
            $query = str_replace('?', '', $query);
            parse_str($query, $querys);
            foreach ($querys as $key => $value) {
                if (!isset($params[$key]) || $params[$key] != $value) {
                    return false;
                }
            }
        }

        // 只允许特定小程序场景值
        if (!empty($config->scene_list)) {
            if (strpos($config->scene_list, $scene) === false) {
                return false;
            }
        }
        // 限制特定小程序场景值
        if (!empty($config->limit_scene_list)) {
            if (strpos($config->limit_scene_list, $scene) !== false) {
                return false;
            }
        }

        // 判断ip限制
        if (empty($ipinfo)) {
            $ip = YqExtend::getIP();
            $ipinfo = IpToolService::getInstance()->getAndCreate($ip);
        }
        // 只允许特定省份
        if (!empty($config->province_list)) {
            if (empty($ipinfo['province']) || strpos($config->province_list, $ipinfo['province']) === false) {
                return false;
            }
        }
        // 只允许特定城市
        if (!empty($config->city_list)) {
            if (empty($ipinfo['city']) || strpos($config->city_list, $ipinfo['city']) === false) {
                return false;
            }
        }
        // 限制特定省份
        if (!empty($config->limit_province_list)) {
            if (!empty($ipinfo['province']) && strpos($config->limit_province_list, $ipinfo['province']) !== false) {
                return false;
            }
        }
        // 限制特定城市
        if (!empty($config->limit_city_list)) {
            if (!empty($ipinfo['city']) && strpos($config->limit_city_list, $ipinfo['city']) !== false) {
                return false;
            }
        }

        return true;
    }

    private function getInitByPage($config, $openid, $params)
    {
        return [
            'type'   => $config->jump_page_type,
            'path'   => "{$config->jump_page}",
            'params' => $params,
        ];
    }

    private function getInitByH5($config, $openid, $params, $launch_info = [])
    {
        // 如果已经携带了跳转
        if (isset($params['mini_h5url'])) {
            $url = $params['mini_h5url'];
        } else {
            $query = http_build_query($params);
            if (strpos($config->jump_url, '?') !== false) {
                $url = "{$config->jump_url}&{$query}";
            } else {
                $url = "{$config->jump_url}?{$query}";
            }
        }

        // 如果是黑土的产品
        if (in_array($config->appid, ['wx136f82abf47fde25', 'wx8f1fab71c9eb347f'])) {
            $query = [
                'mini_openid' => $params['wxopenid'],
                'duid' => $params['wxopenid'],
                'install' => $params['is_first']?1:0,
                'mini_appid' => $config->appid,
                'launchoption' => base64_encode(json_encode($launch_info)),
            ];
            $query = http_build_query($query);
            if (strpos($config->jump_url, '?') !== false) {
                $url = "{$config->jump_url}&{$query}";
            } else {
                $url = "{$config->jump_url}?{$query}";
            }
        }

        return [
            'path'   => $config->jump_url_path,
            'params' => ['url' => $url]
        ];
    }

    private function getInitByMiniprogram($config, $openid, $params)
    {
        if (!empty($config->jump_mini_query)) {
            $query = $config->jump_mini_query;
            $query = str_replace('?', '', $query);
            parse_str($query, $querys);
            foreach ($querys as $key => $value) {
                $params[$key] = $value;
            }
        }

        if (!isset($params['mini_h5url'])) {
            $h5 = $this->getInitByH5($config, $openid, $params);
            $params['mini_h5url'] = $h5['params']['url'];
        }

        return [
            'path'       => '/pages/mtg/mini/index',
            'jump_appid' => $config->jump_mini_appid,
            'jump_path'  => $config->jump_mini_path,
            'params'     => $params,
        ];
    }

    public function getJumpInfo(WxMiniprogramJumpgameConfig $config, $openid, $params, $jump_type, $launch_info)
    {
        $params['xcx_appid'] = $config->appid;
        $params['wxopenid'] = $openid;
        $data = [
            'type' => $jump_type,
        ];

        switch ($jump_type) {
            case LogWxMiniprogramJumpgame::JUMP_TYPE_PAGE:
                $data['page'] = $this->getInitByPage($config, $openid, $params);
                break;
            case LogWxMiniprogramJumpgame::JUMP_TYPE_H5:
                $data['h5'] = $this->getInitByH5($config, $openid, $params, $launch_info);
                break;
            case LogWxMiniprogramJumpgame::JUMP_TYPE_MINI_PROGRAM:
                $data['mini'] = $this->getInitByMiniprogram($config, $openid, $params);
                break;
        }

        return $data;
    }

    public function getJumpByJumpType(LogWxMiniprogramJumpgame $class, $jump_type)
    {
        // 先H5后小程序
        if ($jump_type == LogWxMiniprogramJumpgame::JUMP_TYPE_H5_MINI_PROGRAM) {
            if ($class->login_num < 1) {
                return LogWxMiniprogramJumpgame::JUMP_TYPE_H5;
            } else {
                return LogWxMiniprogramJumpgame::JUMP_TYPE_MINI_PROGRAM;
            }
        }

        return $jump_type;
    }

    public function getStartInfo($appid, $openid, $scene, $params, $launch_info = [])
    {
        $config = WxMiniprogramJumpgameConfig::where('appid', $appid)->first();
        if (!$config) {
            return [];
        }

        // 拿到用户ip信息
        $ip = YqExtend::getIP();
        $ipinfo = IpToolService::getInstance()->getAndCreate($ip);

        // 获取用户历史，如果之前访问过，则保持之前的方式进入
        $class = LogWxMiniprogramJumpgame::whereRaw("openid='{$openid}' AND appid='{$appid}'")->first();
        if ($class) {
            $jump_type = $class->jump_type;
        } else {
            // 判断能否跳转
            if(!$this->canJump($config, $openid, $params, $ipinfo, $scene)) {
                // 如果不能跳转则访问小程序页面
                $jump_type = WxMiniprogramJumpgameConfig::JUMP_TYPE_PAGE;
            } else {
                $jump_type = $config->jump_type;
            }
        }

        $is_first = false;
        if (!$class) {
            $is_first           = true;
            $class              = new LogWxMiniprogramJumpgame;
            $class->create_time = time();
            $class->appid       = $appid;
            $class->openid      = $openid;
            $class->scene       = $scene;
            $class->ip          = $ip;
            $class->jump_type   = $jump_type;
            $class->login_num   = 0;
            $class->launch_info = json_encode($params, JSON_UNESCAPED_UNICODE);
        }

        $jump = $this->getJumpByJumpType($class, $jump_type);
        if ($class->login_num < 1) {
            $class->first_jump = $jump;
        }

        $class->login_time  = time();
        $class->login_ip    = $ip;
        $class->login_jump  = $jump;
        $class->login_scene = $scene;
        $class->login_num   = $class->login_num+1;
        $class->save();

        $params['is_first'] = $is_first;
        $data = $this->getJumpInfo($config, $openid, $params, $jump, $launch_info);
        $data['is_first'] = $is_first;
        return $data;
    }
}
